/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.activity;

import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import org.eclipse.uml2.uml.AcceptCallAction;
import org.eclipse.uml2.uml.AcceptEventAction;
import org.eclipse.uml2.uml.Action;
import org.eclipse.uml2.uml.Activity;
import org.eclipse.uml2.uml.ActivityFinalNode;
import org.eclipse.uml2.uml.ActivityParameterNode;
import org.eclipse.uml2.uml.AddStructuralFeatureValueAction;
import org.eclipse.uml2.uml.AddVariableValueAction;
import org.eclipse.uml2.uml.BroadcastSignalAction;
import org.eclipse.uml2.uml.CallBehaviorAction;
import org.eclipse.uml2.uml.CallOperationAction;
import org.eclipse.uml2.uml.CentralBufferNode;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.ControlFlow;
import org.eclipse.uml2.uml.DataStoreNode;
import org.eclipse.uml2.uml.DecisionNode;
import org.eclipse.uml2.uml.DestroyObjectAction;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.FlowFinalNode;
import org.eclipse.uml2.uml.ForkNode;
import org.eclipse.uml2.uml.InitialNode;
import org.eclipse.uml2.uml.InputPin;
import org.eclipse.uml2.uml.JoinNode;
import org.eclipse.uml2.uml.MergeNode;
import org.eclipse.uml2.uml.ObjectFlow;
import org.eclipse.uml2.uml.OpaqueAction;
import org.eclipse.uml2.uml.OutputPin;
import org.eclipse.uml2.uml.ReadExtentAction;
import org.eclipse.uml2.uml.SendObjectAction;
import org.eclipse.uml2.uml.SendSignalAction;
import org.eclipse.uml2.uml.TestIdentityAction;
import org.eclipse.uml2.uml.UnmarshallAction;
import org.eclipse.uml2.uml.ValueSpecificationAction;

import com.cea.papyrus.core.editor.EditpartFactoryBase;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.AnchorEditPart;
import com.cea.papyrus.core.editpart.GraphEdgeEditPart;
import com.cea.papyrus.core.editpart.GraphNodeWithSemanticEditPart;
import com.cea.papyrus.diagram.activity.editpart.AcceptCallActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.AcceptEventActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.ActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.ActionInputPinEditPart;
import com.cea.papyrus.diagram.activity.editpart.ActivityDiagramEditPart;
import com.cea.papyrus.diagram.activity.editpart.ActivityEditPart;
import com.cea.papyrus.diagram.activity.editpart.ActivityFinalNodeEditPart;
import com.cea.papyrus.diagram.activity.editpart.ActivityParameterNodeEditPart;
import com.cea.papyrus.diagram.activity.editpart.AddStructuralFeatureValueActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.AddVariableValueActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.BroadcastSignalActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.CallBehaviorActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.CallOperationActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.CentralBufferNodeEditPart;
import com.cea.papyrus.diagram.activity.editpart.ControlFlowEditPart;
import com.cea.papyrus.diagram.activity.editpart.CreateObjectActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.DataStoreNodeEditPart;
import com.cea.papyrus.diagram.activity.editpart.DecisionNodeEditPart;
import com.cea.papyrus.diagram.activity.editpart.DestroyObjectActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.FlowFinalNodeEditPart;
import com.cea.papyrus.diagram.activity.editpart.ForkNodeEditPart;
import com.cea.papyrus.diagram.activity.editpart.InitialNodeEditPart;
import com.cea.papyrus.diagram.activity.editpart.InputPinEditPart;
import com.cea.papyrus.diagram.activity.editpart.JoinNodeEditPart;
import com.cea.papyrus.diagram.activity.editpart.MergeNodeEditPart;
import com.cea.papyrus.diagram.activity.editpart.ObjectFlowEditPart;
import com.cea.papyrus.diagram.activity.editpart.OpaqueActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.OutputPinEditPart;
import com.cea.papyrus.diagram.activity.editpart.PinNameDisplayEditPart;
import com.cea.papyrus.diagram.activity.editpart.ReadExtentActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.SendObjectActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.SendSignalActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.TestIdentityActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.UnmarshallActionEditPart;
import com.cea.papyrus.diagram.activity.editpart.ValueSpecificationActionEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.CommentEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ConstraintEditPart;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphEdge;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Manages creation of controllers for deployment diagram elements.
 */
public class ActivityDiagramGraphicalEditPartsFactory extends EditpartFactoryBase implements
		EditPartFactory {

	/**
	 * The model manager.
	 */
	protected ModelManager modelManager;

	/**
	 * Creates the edit part.
	 * 
	 * @param obj the obj
	 * @param context the context
	 * 
	 * @return the edit part
	 */
	public EditPart createEditPart(EditPart context, Object obj) {
		
		//new mechanism
		EditPart result= getEditPartFromProperty(context, obj,modelManager);
		if (result!=null){
			return result;
		}
		// to identify the good editpart we need the nature of the object
		// graphEdge or graphNode and
		// uml Elment connected
		// case of a diagram
		if (obj instanceof Diagram) {
			return new ActivityDiagramEditPart((Diagram) obj, modelManager);
		} else if (obj instanceof GraphNode) {
			if (((GraphNode) obj).getSemanticParent() != null && ((Uml1SemanticModelBridge)((GraphElement)((GraphNode) obj).getSemanticParent()).getSemanticModel()).getElement() instanceof InputPin) {
				Element umlSemanticParent= ((Uml1SemanticModelBridge)((GraphElement)((GraphNode) obj).getSemanticParent()).getSemanticModel()).getElement();
				((GraphNode) obj).setSemanticModel(null);
				return new PinNameDisplayEditPart((GraphNode) obj,umlSemanticParent, modelManager);
			}
			if (((GraphNode) obj).getSemanticParent() != null && ((Uml1SemanticModelBridge)((GraphElement)((GraphNode) obj).getSemanticParent()).getSemanticModel()).getElement() instanceof OutputPin) {
				Element umlSemanticParent= ((Uml1SemanticModelBridge)((GraphElement)((GraphNode) obj).getSemanticParent()).getSemanticModel()).getElement();
				((GraphNode) obj).setSemanticModel(null);
				return new PinNameDisplayEditPart((GraphNode) obj,umlSemanticParent, modelManager);
			}
			if (((Uml1SemanticModelBridge) ((GraphNode) obj).getSemanticModel()) == null) {
				return new AnchorEditPart((GraphNode) obj, modelManager);
			}
			if ((((Uml1SemanticModelBridge) ((GraphNode) obj)
					.getSemanticModel()).getElement()) == null) {
				return new GraphNodeWithSemanticEditPart((GraphNode) obj,
						modelManager);
			}
			Element elt = ((Uml1SemanticModelBridge) ((GraphNode) obj)
					.getSemanticModel()).getElement();
			return searchEditPart((GraphNode) obj, elt);
		}
	
		// case of a graphEdge
		else if (obj instanceof GraphEdge) {
			if (((Uml1SemanticModelBridge) ((GraphEdge) obj).getSemanticModel()) != null) {
				if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof ControlFlow) {
					return new ControlFlowEditPart((GraphEdge) obj, modelManager);
				} else if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof ObjectFlow) {
					return new ObjectFlowEditPart((GraphEdge) obj, modelManager);
				} 	
			} else {
				GraphEdge ge = (GraphEdge) obj;
				return new GraphEdgeEditPart(ge, modelManager);
			}
		}
		return null;
	}

	/**
	 * The Constructor.
	 * 
	 * @param modelManager the model manager
	 */
	public ActivityDiagramGraphicalEditPartsFactory(ModelManager modelManager) {
		this.modelManager = modelManager;
	}

	/**
	 * Search edit part.
	 * 
	 * @param graphNode the graph node
	 * @param elt the elt
	 * 
	 * @return the edit part
	 */
	public EditPart searchEditPart(GraphNode graphNode, Element elt) {
		// Type elements
		if (elt instanceof ElementImport) {
			// in the case of element Import, we need to recall this method
			return searchEditPart(graphNode, ((ElementImport) elt)
					.getImportedElement());
		}
		// Object Nodes
		// DataStoreNode
		if (elt instanceof DataStoreNode) {
			return new DataStoreNodeEditPart(graphNode, modelManager);
		}
		// CentralBufferNode
		if (elt instanceof CentralBufferNode) {
			return new CentralBufferNodeEditPart(graphNode, modelManager);
		}
		// ActivityParameterNode
		if (elt instanceof ActivityParameterNode) {
			return new ActivityParameterNodeEditPart(graphNode, modelManager);
		}
		
		// Pins
		// ActionInputPin
		if (elt instanceof InputPin) {
			return new ActionInputPinEditPart(graphNode, modelManager);
		}
		// InputPin
		if (elt instanceof InputPin) {
			return new InputPinEditPart(graphNode, modelManager);
		}
		// OutputPin
		if (elt instanceof OutputPin) {
			return new OutputPinEditPart(graphNode, modelManager);
		}
		
		// Actions
		// CallOperationAction
		if (elt instanceof CallOperationAction) {
			return new CallOperationActionEditPart(graphNode, modelManager);
		}
		// OpaqueAction
		if (elt instanceof OpaqueAction) {
			return new OpaqueActionEditPart(graphNode, modelManager);
		}
		
		// BroadcastSignalAction
		if (elt instanceof BroadcastSignalAction) {
			return new BroadcastSignalActionEditPart(graphNode, modelManager);
		}
		// CallBehaviorAction
		if (elt instanceof CallBehaviorAction) {
			return new CallBehaviorActionEditPart(graphNode, modelManager);
		}
		// SendSignalAction
		if (elt instanceof SendSignalAction) {
			return new SendSignalActionEditPart(graphNode, modelManager);
		}
		// SendObjectAction
		if (elt instanceof SendObjectAction) {
			return new SendObjectActionEditPart(graphNode, modelManager);
		}
		// ValueSpecificationAction
		if (elt instanceof ValueSpecificationAction) {
			return new ValueSpecificationActionEditPart(graphNode, modelManager);
		}
		// TestIdentityAction
		if (elt instanceof TestIdentityAction) {
			return new TestIdentityActionEditPart(graphNode, modelManager);
		}
		// AcceptEventAction
		if (elt instanceof AcceptEventAction) {
			return new AcceptEventActionEditPart(graphNode, modelManager);
		}
		// AcceptCallAction
		if (elt instanceof AcceptCallAction) {
			return new AcceptCallActionEditPart(graphNode, modelManager);
		}
		
		// UnmarshallAction
		if (elt instanceof UnmarshallAction) {
			return new UnmarshallActionEditPart(graphNode, modelManager);
		}
		// AddVariableAction
		if (elt instanceof AddVariableValueAction) {
			return new AddVariableValueActionEditPart(graphNode, modelManager);
		}
		
		//	Activity
		if (elt instanceof Activity) {
			return new ActivityEditPart(graphNode, modelManager);
		}
		
		//	Decision Node
		if (elt instanceof DecisionNode) {
			return new DecisionNodeEditPart(graphNode, modelManager);
		}
		
		//	Actitivity Final Node
		if (elt instanceof ActivityFinalNode) {
			return new ActivityFinalNodeEditPart(graphNode, modelManager);
		}
		
		// Flow Final Node
		if (elt instanceof FlowFinalNode) {
			return new FlowFinalNodeEditPart(graphNode, modelManager);
		}
		
		//	Fork Node
		if (elt instanceof MergeNode) {
			return new MergeNodeEditPart(graphNode, modelManager);
		}
		
		//	Initial Node
		if (elt instanceof InitialNode) {
			return new InitialNodeEditPart(graphNode, modelManager);
		}
		
		//	Join Node
		if (elt instanceof JoinNode) {
			return new JoinNodeEditPart(graphNode, modelManager);
		}
		
		//	Fork Node
		if (elt instanceof ForkNode) {
			return new ForkNodeEditPart(graphNode, modelManager);
		}
		
		// Constraint
		if (elt instanceof Constraint) {
			return new ConstraintEditPart(graphNode, modelManager);
		}
		// Comment
		if (elt instanceof Comment) {
			return new CommentEditPart(graphNode, modelManager);
		}
		// CreateObjectAction
		if (elt instanceof org.eclipse.uml2.uml.CreateObjectAction) {
			return new CreateObjectActionEditPart(graphNode, modelManager);
		}
		
		// DestroyObjectAction
		if (elt instanceof DestroyObjectAction) {
			return new DestroyObjectActionEditPart(graphNode, modelManager);
		}
		// ReadExtentAction
		if (elt instanceof ReadExtentAction) {
			return new ReadExtentActionEditPart(graphNode, modelManager);
		}
		// AddStructuralFeatureValueAction
		if (elt instanceof AddStructuralFeatureValueAction) {
			return new AddStructuralFeatureValueActionEditPart(graphNode, modelManager);
		}
		// Comment
		if (elt instanceof Comment) {
			return new CommentEditPart(graphNode, modelManager);
		}
		if (elt instanceof Action) {
			return new ActionEditPart(graphNode, modelManager);
		}
		return null;
	}
}